Some principles

参考《重构—改善既有代码的设计》(《Refactoring—Improving the Design of Existing Code》).

重构(Refactoring)

所谓重构是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。本质上说,重构就是在代码写好之后改进它的设计。

『在代码写好后改进它的设计』,似乎不是合理的方式,按照目前对软件开发的理解,我们要相信先设计再编码。但是在开始是很难完全预测后面可能会出现的变更,在设计前期使用模式常常导致过度工程(over-engineering),随着时间流逝,人们不断修改代码,则会导致系统原来的设计不可避免的混乱。

重构则与此相反。即使目前是一堆混乱的代码,我们也可以借由重构将其加工成设计良好的代码。重构的目的是使软件更容易被理解和修改。

重构定义:

  • 名词:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
  • 动词:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

使用重构技术开发软件时,你应该把时间分配给两种截然不同的行为:添加新功能,以及重构。添加新功能时,你不应该修改既有代码,只管添加新功能,通过测试。重构时就不能同时添加新功能。

Why refactoring

  • 重构改进软件设计
    如果没有重构,程序的设计会逐渐腐败变质。

  • 重构是代码更容易理解
    所谓程序设计,很大程度上就是与计算机交谈。很多时候我们需要补上或修改想要它做什么。而这种编程模式的核心就是『准确说出我想要的』,让代码更易读。

  • 重构帮助找到bug

  • 重构提高编程速度

系统当下的行为,只是故事的一部分。如果只是为今天工作,明天可能无法继续下去。重构是一条摆脱困境的道路。

下面的程序将会使改动困难重重,导致代码僵化并死亡:

  • 难以阅读的程序,难以修改
  • 逻辑重复的程序,难以修改
  • 添加新行为时需要修改已有代码的程序,难以修改
  • 带复杂条件逻辑的程序,难以修改

我们希望程序:(1)容易阅读 (2)所有逻辑都只在唯一的位置指定,没有重复 (3)新的改动不会危及现有行为 (4)尽可能简单表达条件逻辑、

重构可以帮助我们在不改变程序行为的前期下使其具有上述美好性质,使我们更能够继续保持高速开发。

When refactoring

第一次做某件事尽管去做;第二次做类似的事如果产生反感,但还是可以去做;第三次再做类似的事,你就应该重构,

  • 添加功能时重构
    如果不能轻松天骄所需要的新功能

  • 修补错误时重构
    如果难以找出程序的bug。

  • 复审代码时重构

Refactoring and Design

重构肩负一项特殊使命:它和设计彼此互补。如果没有重构,你就必须保证预先做出的设计正确无误,但这个难度太大了,过度的预先设计往往反而会导致程序的难以编写。如果选择重构,问题的重点就转变了。你仍然可以预先设计,但是不必找到正确的解决方案(事实上也是不可能的),而是一个足够合理的解决方案就够了。

预先设计往往要预测后面可能的变化,力求得到灵活的解决方案。但是很难预测所有的变化,变化其实可能出现系统各处,如果在所有可能出现变化的地方都建立起灵活性,则往往需要建立许多中间层,反而使系统复杂且难以理解和维护。如果最后发现所有这些灵活性其实毫无必要,才是最大的失败。

重构可以带来更简单的设计,同时不损失灵活性,这也降低了设计过程的难度,减轻设计压力。

Some pricinples:

  • 如果你发现自己需要为程序添加一个特性,而代码结构使你无法很方便地达成目的,那就先重构哪个程序,是特性的添加比较容易进行,然后在添加特性。
  • 重构的第一步:建立一组可靠的测试机制,这些测试必须有自我校验能力。
  • 好的代码应该清楚表达出自己的功能,变量名称是代码清晰的关键。
  • 尽量不要使用临时变量,它们会导致大量参数传来传去,难以追踪,导致冗长的函数。